package cn.jingzhuan.element.demo.view.util.audio

import android.content.*
import android.os.Build
import android.os.IBinder
import cn.jingzhuan.element.demo.App
import java.util.concurrent.TimeUnit

/**
 * Created by KNOX.
 */
object AudioPlayerManager {
  
  private var currentAudio : Audio? = null
  private var audioService : AudioService? = null
  private var playStatus : PlayStatus? = null
  private var serviceBinder : ServiceBinder? = null
  private var isPaused = false
  private var isBound = false
  
  fun bindService(serviceConnection : ServiceConnection) : ServiceToken? {
    val contextWrapper = ContextWrapper(App.instance)
    val intent = Intent(contextWrapper, AudioService::class.java)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      contextWrapper.startForegroundService(intent)
    } else {
      contextWrapper.startService(intent)
    }
    serviceBinder = ServiceBinder(serviceConnection)
    if (App.instance.bindService(intent, serviceBinder, Context.BIND_AUTO_CREATE)) {
      isBound = true
      return ServiceToken(App.instance)
    }
    
    return null
  }
  
  fun unbindService() {
    if (serviceBinder != null && audioService != null && isBound) {
      App.instance.unbindService(serviceBinder)
      audioService = null
    }
    if (currentAudio != null) {
      currentAudio = null
    }
    isBound = false
  }
  
  fun play(forwardToLastTime : Boolean) {
    if (audioService != null && currentAudio != null) {
      isPaused = false
      audioService?.play()
      playStatus?.playing()
      if (forwardToLastTime) {
        seekTo(TimeUnit.SECONDS.toMillis(currentAudio?.lastPlayTime!!).toInt())
      }
    }
  }
  
  fun resume() {
    if (audioService != null) {
      isPaused = false
      audioService?.resume()
      playStatus?.playing()
    }
  }
  
  fun seekTo(second : Int) {
    if (audioService != null) {
      audioService?.seekTo(second)
    }
  }
  
  fun pause() {
    if (audioService != null) {
      isPaused = true
      audioService?.pause()
    }
  }
  
  fun paused() = isPaused
  
  fun stop() {
    if (currentAudio != null && audioService != null) {
      currentAudio = null
      App.instance.serviceToken = null
      audioService?.stop()
    }
  }
  
  fun isPlaying() = audioService != null && audioService?.isPlaying() !!
  
  fun duration() : Long? = audioService?.duration()
  
  fun currentPosition() : Long? = audioService?.currentPosition()
  
  fun setupAudio(audio : Audio?) {
    this.currentAudio = audio
  }
  
  fun changeAudio(audio : Audio?,status : AudioService.PrepareStatus?) {
    this.currentAudio = audio
    status?.let { audioService?.withPrepareStatus(it)?.preparing(audio) }
  }
  
  fun prepareAudio(status : AudioService.PrepareStatus?) {
    if (this.currentAudio != null) {
      status?.let { audioService?.withPrepareStatus(it)?.preparing(currentAudio) }
    }
  }
  
  fun currentAudio() : Audio? = this.currentAudio
  
  fun currentAudioService() : AudioService? = audioService
  
  class ServiceBinder(private val callback : ServiceConnection) : ServiceConnection {
    
    override fun onServiceDisconnected(componentName : ComponentName?) {
      callback.onServiceDisconnected(componentName)
      audioService = null
    }
    
    override fun onServiceConnected(componentName : ComponentName?, iBinder : IBinder?) {
      val binder : AudioService.AudioBinder? = iBinder as AudioService.AudioBinder
      if (binder != null) {
        audioService = binder.service
        callback.onServiceConnected(componentName, binder)
      }
    }
    
  }
  
  class ServiceToken(val context : Context?)
  
  interface PlayStatus {
    fun playing()
  }
  
  fun withStatus(status : PlayStatus?) : AudioPlayerManager {
    this.playStatus = status
    return this
  }
  
  fun removeStatus() {
    this.playStatus = null
    this.audioService?.removePrepareStatus()
  }
}